{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# lgo and interrupt\n",
    "This notebook demonstrates you can interrupts lgo execution in Jupyter notebook.\n",
    "To interrupt code in Jupyter Notebook, please press the stop button in the toolbar or press `I, I` in command mode."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# For-loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "interrupted"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i = 314720394, sum = 49524463042397421, i*(i-1)/2 = 49524463042397421\n"
     ]
    }
   ],
   "source": [
    "import (\n",
    "    \"fmt\"\n",
    ")\n",
    "\n",
    "var sum, i int64\n",
    "defer func() {\n",
    "    fmt.Printf(\"i = %d, sum = %d, i*(i-1)/2 = %d\\n\", i, sum, i*(i-1)/2)\n",
    "}()\n",
    "for i = int64(0);; i++ {\n",
    "    sum += i\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# recursion\n",
    "You can interrupt heavy recursive functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "time: 13.047495052s\n",
      "leaf counter: 1483226484\n",
      "avg: 8ns/cycle\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "interrupted"
     ]
    }
   ],
   "source": [
    "import (\n",
    "    \"fmt\"\n",
    "    \"time\"\n",
    ")\n",
    "\n",
    "leaf := 0\n",
    "\n",
    "func naiveFib(n int64) int64 {\n",
    "    if n < 2 {\n",
    "        leaf++\n",
    "        return 1\n",
    "    }\n",
    "    return naiveFib(n-1) + naiveFib(n-2)\n",
    "}\n",
    "\n",
    "start := time.Now()\n",
    "defer func(){\n",
    "    end := time.Now()\n",
    "    fmt.Printf(\"time: %v\\n\", end.Sub(start))\n",
    "    fmt.Printf(\"leaf counter: %d\\n\", leaf)\n",
    "    fmt.Printf(\"avg: %v/cycle\\n\", end.Sub(start)/time.Duration(leaf))\n",
    "}()\n",
    "naiveFib(50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# channel and select"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "interrupted\n"
     ]
    }
   ],
   "source": [
    "{\n",
    "    c := make(chan int)\n",
    "    // Block forever because no one reads c.\n",
    "    c <- 10\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "interrupted\n"
     ]
    }
   ],
   "source": [
    "{\n",
    "    c := make(chan int)\n",
    "    // Block forever because no one sends an int to c.\n",
    "    <-c\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "interrupted\n"
     ]
    }
   ],
   "source": [
    "{\n",
    "    c0, c1 := make(chan int), make(chan int)\n",
    "    // Block forever because no one read or write c0 and c1.\n",
    "    select {\n",
    "    case c0 <- 10:\n",
    "        fmt.Println(\"Sent an int to c0\")\n",
    "    case i := <-c1:\n",
    "        fmt.Println(\"Received\", i)\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# goroutine"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i = 0 (in goroutine)\n"
     ]
    }
   ],
   "source": [
    "import (\n",
    "    \"fmt\"\n",
    ")\n",
    "\n",
    "go func() {\n",
    "    var i int64\n",
    "    defer func() {\n",
    "        fmt.Printf(\"i = %d (in goroutine)\\n\", i)\n",
    "    }()\n",
    "    for i = 0 ;; i++ {}\n",
    "}()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Go libraries\n",
    "lgo creates a special context `_ctx` on every execution and `_ctx` is cancelled when the execution is cancelled. Please pass `_ctx` as a context.Context param of Go libraries you want to cancel (See [README.md](https://github.com/yunabe/lgo/blob/master/README.md#cancellation))."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Failed: Get https://yunabe-codelab.appspot.com/slow?sec=10: context canceled"
     ]
    }
   ],
   "source": [
    "// This demo demostrates how to use net/http with cancellation in lgo.\n",
    "import (\n",
    "    \"fmt\"\n",
    "    \"io/ioutil\"\n",
    "    \"net/http\"\n",
    ")\n",
    "\n",
    "{\n",
    "    waitSec := 10\n",
    "    var err error\n",
    "    defer func() {\n",
    "        if err != nil {\n",
    "            fmt.Printf(\"Failed: %v\", err)\n",
    "        }\n",
    "    }()\n",
    "    url := fmt.Sprintf(\"https://yunabe-codelab.appspot.com/slow?sec=%d\", waitSec)\n",
    "    req, err := http.NewRequest(\"GET\", url, nil)\n",
    "    if err != nil {\n",
    "        return\n",
    "    }\n",
    "    res, err := http.DefaultClient.Do(req.WithContext(_ctx))\n",
    "    if err != nil {\n",
    "        return\n",
    "    }\n",
    "    b, err := ioutil.ReadAll(res.Body)\n",
    "    if err != nil {\n",
    "        return\n",
    "    }\n",
    "    fmt.Printf(\"Got: %q\", b)\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Go (lgo)",
   "language": "go",
   "name": "lgo"
  },
  "language_info": {
   "file_extension": "",
   "mimetype": "",
   "name": "go",
   "version": ""
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
